package com.example.calendar.ui.screens.event

import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.calendar.data.model.CalendarEvent
import com.example.calendar.data.repository.CategoryRepository
import com.example.calendar.data.repository.EventRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalDateTime
import org.threeten.bp.LocalTime
import java.util.UUID
import javax.inject.Inject

/**
 * ViewModel for creating and editing events
 */
@HiltViewModel
class EventViewModel @Inject constructor(
    private val eventRepository: EventRepository,
    private val categoryRepository: CategoryRepository,
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {
    
    // The ID of the event being edited, or null if creating a new event
    private val eventId: String? = savedStateHandle.get<String>("eventId")
    
    // State for the UI
    private val _uiState = MutableStateFlow(EventUiState())
    val uiState: StateFlow<EventUiState> = _uiState.asStateFlow()
    
    init {
        // If we have an eventId, load the event details
        eventId?.let { id ->
            loadEvent(id)
        }
    }
    
    /**
     * Load event details from the repository
     */
    private fun loadEvent(id: String) {
        viewModelScope.launch {
            eventRepository.getEventById(id).collect { event ->
                event?.let {
                    _uiState.update { currentState ->
                        currentState.copy(
                            id = it.id,
                            title = it.title,
                            description = it.description ?: "",
                            location = it.location ?: "",
                            startDateTime = it.startDateTime,
                            endDateTime = it.endDateTime,
                            isAllDay = it.isAllDay,
                            reminderMinutes = it.reminderMinutes,
                            categoryId = it.categoryId,
                            color = it.color,
                            isLoading = false,
                            isEditing = true
                        )
                    }
                }
            }
        }
    }
    
    /**
     * Create a new event with the current UI state
     */
    fun createEvent() {
        val state = uiState.value
        
        if (state.title.isBlank()) {
            _uiState.update { it.copy(error = "Title cannot be empty") }
            return
        }
        
        if (state.endDateTime.isBefore(state.startDateTime)) {
            _uiState.update { it.copy(error = "End time must be after start time") }
            return
        }
        
        val event = CalendarEvent(
            id = state.id ?: UUID.randomUUID().toString(),
            title = state.title,
            description = state.description.takeIf { it.isNotBlank() },
            location = state.location.takeIf { it.isNotBlank() },
            startDateTime = state.startDateTime,
            endDateTime = state.endDateTime,
            isAllDay = state.isAllDay,
            reminderMinutes = state.reminderMinutes,
            categoryId = state.categoryId,
            color = state.color
        )
        
        viewModelScope.launch {
            if (state.isEditing) {
                eventRepository.updateEvent(event)
            } else {
                eventRepository.addEvent(event)
            }
        }
    }
    
    // UI State Update Functions
    
    fun updateTitle(title: String) {
        _uiState.update { it.copy(title = title) }
    }
    
    fun updateDescription(description: String) {
        _uiState.update { it.copy(description = description) }
    }
    
    fun updateLocation(location: String) {
        _uiState.update { it.copy(location = location) }
    }
    
    fun updateAllDay(isAllDay: Boolean) {
        _uiState.update { currentState ->
            val updatedState = currentState.copy(isAllDay = isAllDay)
            
            // If switching to all day, update times to be start/end of day
            if (isAllDay && !currentState.isAllDay) {
                val startDateTime = currentState.startDateTime.toLocalDate().atStartOfDay()
                val endDateTime = currentState.endDateTime.toLocalDate().atTime(LocalTime.MAX)
                updatedState.copy(startDateTime = startDateTime, endDateTime = endDateTime)
            } else {
                updatedState
            }
        }
    }
    
    fun updateStartDate(date: LocalDate) {
        _uiState.update { currentState ->
            // Keep the same time, just change the date
            val newStartDateTime = LocalDateTime.of(
                date,
                currentState.startDateTime.toLocalTime()
            )
            
            // If the new start date is after end date, adjust end date
            val currentEndDate = currentState.endDateTime.toLocalDate()
            if (date.isAfter(currentEndDate)) {
                val newEndDateTime = LocalDateTime.of(
                    date,
                    currentState.endDateTime.toLocalTime()
                )
                currentState.copy(startDateTime = newStartDateTime, endDateTime = newEndDateTime)
            } else {
                currentState.copy(startDateTime = newStartDateTime)
            }
        }
    }
    
    fun updateStartTime(time: LocalTime) {
        _uiState.update { currentState ->
            val newStartDateTime = LocalDateTime.of(
                currentState.startDateTime.toLocalDate(),
                time
            )
            
            // If the new start time is after end time on the same day, adjust end time
            if (currentState.startDateTime.toLocalDate().isEqual(currentState.endDateTime.toLocalDate()) &&
                time.isAfter(currentState.endDateTime.toLocalTime())) {
                val newEndDateTime = LocalDateTime.of(
                    currentState.endDateTime.toLocalDate(),
                    time.plusHours(1)
                )
                currentState.copy(startDateTime = newStartDateTime, endDateTime = newEndDateTime)
            } else {
                currentState.copy(startDateTime = newStartDateTime)
            }
        }
    }
    
    fun updateEndDate(date: LocalDate) {
        _uiState.update { currentState ->
            // Keep the same time, just change the date
            val newEndDateTime = LocalDateTime.of(
                date,
                currentState.endDateTime.toLocalTime()
            )
            
            // If the new end date is before start date, show error but don't update
            if (date.isBefore(currentState.startDateTime.toLocalDate())) {
                currentState.copy(error = "End date cannot be before start date")
            } else {
                currentState.copy(endDateTime = newEndDateTime, error = null)
            }
        }
    }
    
    fun updateEndTime(time: LocalTime) {
        _uiState.update { currentState ->
            val newEndDateTime = LocalDateTime.of(
                currentState.endDateTime.toLocalDate(),
                time
            )
            
            // If the new end time is before start time on the same day, show error but don't update
            if (currentState.startDateTime.toLocalDate().isEqual(currentState.endDateTime.toLocalDate()) &&
                time.isBefore(currentState.startDateTime.toLocalTime())) {
                currentState.copy(error = "End time cannot be before start time")
            } else {
                currentState.copy(endDateTime = newEndDateTime, error = null)
            }
        }
    }
    
    fun updateReminder(reminderMinutes: Int) {
        if (reminderMinutes > 0) {
            _uiState.update { it.copy(reminderMinutes = listOf(reminderMinutes)) }
        }
    }
    
    fun clearError() {
        _uiState.update { it.copy(error = null) }
    }
}

/**
 * UI state for the event screen
 */
data class EventUiState(
    val id: String? = null,
    val title: String = "",
    val description: String = "",
    val location: String = "",
    val startDateTime: LocalDateTime = LocalDateTime.now(),
    val endDateTime: LocalDateTime = LocalDateTime.now().plusHours(1),
    val isAllDay: Boolean = false,
    val reminderMinutes: List<Int> = emptyList(),
    val categoryId: String? = null,
    val color: Int? = null,
    val isLoading: Boolean = false,
    val isEditing: Boolean = false,
    val error: String? = null
) 